// Compress/CopyCoder.cpp

#include "StdAfx.h"

#include "../../../C/Alloc.h"

#include "Common/Stream/StreamUtils.h"

#include "CopyCoder.h"

namespace Common
{
namespace Compress 
{

static const UINT32 kBufferSize = 1 << 17;

void CCopyCoder::FinalRelease()
{
  ::MidFree(_buffer);
}

STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
    ISequentialOutStream *outStream,
    const UINT64 * /* inSize */, const UINT64 *outSize,
    ICompressProgressInfo *progress)
{
  if (_buffer == 0)
  {
    _buffer = (BYTE *)::MidAlloc(kBufferSize);
    if (_buffer == 0)
      return E_OUTOFMEMORY;
  }

  TotalSize = 0;
  HRESULT hRes(S_OK);
  for (;;)
  {
    UINT32 size = kBufferSize;
    if (outSize != 0)
      if (size > *outSize - TotalSize)
        size = (UINT32)(*outSize - TotalSize);
    hRes = inStream->Read(_buffer, size, &size);
	if(S_OK != hRes)
		return hRes;
    if (size == 0)
      break;
    if (outStream)
    {
      hRes = WriteStream(outStream, _buffer, size);
	  if(S_OK != hRes)
		return hRes;
    }
    TotalSize += size;
    if (progress != NULL)
    {
      hRes = progress->SetRatioInfo(&TotalSize, &TotalSize);
	  if(S_OK != hRes)
		return hRes;
    }
  }
  return S_OK;
}

STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UINT64 *value)
{
  *value = TotalSize;
  return S_OK;
}

HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
	Compress::CCopyCoder * stream = new CComObject< Compress::CCopyCoder>;
	stream->FinalConstruct();
	CComPtr<ICompressCoder> copyCoder = stream;
  return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
}

}}
